package com.soap.desensitize.strategy.json;

import com.soap.desensitize.encry.rreversible.asymmetric.AbstractAsymmetryEncry;
import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

/**
 * @desc   普通Json字符串加密策略
 * @author BuffPlum
 * @time   2022-04-27
 */
public class JsonStringStrategy extends AbstractAsymmetryEncry<String> {

    /**
     * 默认密码
     */
    private String password="12345678";

    private static JsonStringStrategy instance = null;

    /**
     * @desc  无参构造
     */
    private JsonStringStrategy(){}

    /**
     * @desc 获得实例
     * @return
     */
    public static synchronized JsonStringStrategy getInstance(){
        if(instance == null){
            instance = new JsonStringStrategy();
        }
        return instance;
    }

    /**
     * 序列化为数组
     * @param message
     * @param key
     * @return
     */
    public byte[]  encryptByte(String message ,String key){
        try {
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            DESKeySpec desKeySpec=new DESKeySpec(key.getBytes(StandardCharsets.UTF_8));
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey secreKey = keyFactory.generateSecret(desKeySpec);
            IvParameterSpec iv = new IvParameterSpec(key.getBytes(StandardCharsets.UTF_8));
            cipher.init(Cipher.ENCRYPT_MODE,secreKey,iv);
            return  cipher.doFinal(message.getBytes(StandardCharsets.UTF_8));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException | InvalidKeyException | InvalidKeySpecException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public  String toHexBinString(byte[] b){
        return HexBin.encode(b);
    }
    public String toHexString(byte[] b){
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            String plainText = Integer.toHexString(0xff & b[i]);
            if(plainText.length()<2){
                plainText = "0" + plainText;
            }
            hexString.append(plainText);
        }
        return hexString.toString();
    }


    public static String decrypt(String value, String key) throws Exception {
        byte[] bytesrc = convertHexString(value);
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
        IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8"));
        cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
        byte[] retByte = cipher.doFinal(bytesrc);
        return java.net.URLDecoder.decode(new String(retByte, "UTF-8"),"utf-8");
    }



    public static byte[] convertHexString(String ss) {
        byte digest[] = new byte[ss.length() / 2];
        for (int i = 0; i < digest.length; i++) {
            String byteString = ss.substring(2 * i, 2 * i + 2);
            int byteValue = Integer.parseInt(byteString, 16);
            digest[i] = (byte) byteValue;
        }
        return digest;
    }

    @Override
    public String encode(String data) {
        byte[] b = encryptByte(data,password);

        
        return toHexString(b);
    }

    @Override
    public String decode(String data) {
        String str;
        try {
             str = decrypt(data, password);
             return  str;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


}
